package com.whale.kernel.service.hibernate;

import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import javax.xml.stream.XMLInputFactory;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;

public abstract class AbstractHibernateService {

	protected HibernateTemplate hibernateTemplate;

	public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
		this.hibernateTemplate = hibernateTemplate;
	}

	@SuppressWarnings("unchecked")
	protected <T> List<T> getQueryResult(Class<T> clazz, final String strQuery,
			final Map<String, Object> parameters, final Integer firstResult,
			final Integer maxResult) {
		return hibernateTemplate.executeFind(new HibernateCallback<List<T>>() {

			public List<T> doInHibernate(Session session) throws HibernateException,
					SQLException {
				Query query = session.createQuery(strQuery);
				if (parameters != null) {
					setQueryParameters(parameters, query);
				}
				if (firstResult != null && maxResult != null) {
					query.setFirstResult(firstResult).setMaxResults(maxResult);
				}
				return query.list();
			}
		});
	}
	
	protected <T> List<T> getQueryResult(Class<T> clazz, final String strQuery,
			final Map<String, Object> parameters) {
		return getQueryResult(clazz, strQuery, parameters, null, null);
	}
	
	protected <T> List<T> getQueryResult(Class<T> clazz, final String strQuery) {
		return getQueryResult(clazz, strQuery, null);
	}
	
	protected <T> T getUniqueQueryResult(Class<T> clazz, final String strQuery,
			final Map<String, Object> parameters) {
		return hibernateTemplate.execute(new HibernateCallback<T>() {

			@SuppressWarnings("unchecked")
			public T doInHibernate(Session session) throws HibernateException,
					SQLException {
				Query query = session.createQuery(strQuery);
				if (parameters != null) {
					setQueryParameters(parameters, query);
				}
				return (T)query.uniqueResult();
			}
		});
	}
	
	protected <T> T getUniqueQueryResult(Class<T> clazz, final String strQuery) {
		return getUniqueQueryResult(clazz, strQuery, null);
	}
	
	protected void executeUpdate(final String strQuery,
			final Map<String, Object> parameters) {
		hibernateTemplate.execute(new HibernateCallback<Object>() {

			public Object doInHibernate(Session session) throws HibernateException,
					SQLException {
				Query query = session.createQuery(strQuery);
				if (parameters != null) {
					setQueryParameters(parameters, query);
				}
				query.executeUpdate();
				return null;
			}
		});
	}
	
	protected void executeUpdate(final String strQuery) {
		executeUpdate(strQuery, null);
	}

	protected void setQueryParameters(Map<String, Object> values, Query query) {
		for (String key : values.keySet()) {
			query.setParameter(key, values.get(key));
		}
	}
	
	protected XMLInputFactory createXMLInputFactory() {
		XMLInputFactory xmlif = XMLInputFactory.newInstance();
        xmlif.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, Boolean.TRUE);
        xmlif.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE);

        // Important:
        xmlif.setProperty(XMLInputFactory.IS_COALESCING, Boolean.TRUE);
        return xmlif;
	}
}
